﻿//Manimaran

using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
using Microsoft.VisualBasic.FileIO;

namespace Tzync
{
    public class FolderOperations
    {
        private String storeFilesDir;
        private SafeSync safeSync;
        private Stack<Difference> folderStack;

        public FolderOperations(String storeFilesDir, SafeSync safeSync)
        {
            this.storeFilesDir = storeFilesDir;
            this.safeSync = safeSync;
            folderStack = new Stack<Difference>();
        }

        public TreeNode Creation(Difference diff, SystemType systemName)
        {
            TreeNode tNode = diff.GetPartnerFolder();

            if (diff.GetPairType().First == DirectionType.SystemToHD)
            {
                // To be updated for v2.0
            }
            else
            {
                if (systemName == SystemType.Host)
                {
                    // Create the directory
                    Directory.CreateDirectory(tNode.GetFullPathHost());

                    // Perform safe sync
                    safeSync.Append(SafeSyncType.CreateFolder, tNode.GetFullPathHost());

                    tNode.GetVersionHost().First = tNode.GetVersionGuest().First;
                    tNode.GetVersionHost().Second = tNode.GetVersionGuest().Second;
                }
                else
                {
                    // Create the directory
                    Directory.CreateDirectory(tNode.GetFullPathGuest());

                    // Perform safe sync
                    safeSync.Append(SafeSyncType.CreateFolder, tNode.GetFullPathGuest());

                    Directory.CreateDirectory(tNode.GetFullPathGuest());
                    tNode.GetVersionGuest().First = tNode.GetVersionHost().First;
                    tNode.GetVersionGuest().Second = tNode.GetVersionHost().Second;
                }
            }
            return tNode;
        }

        public TreeNode Deletion(Difference diff, SystemType systemName)
        {
            TreeNode tNode = diff.GetPartnerFolder();

            if (diff.GetPairType().First == DirectionType.SystemToHD)
            {
                if (systemName == SystemType.Host)
                {
                    tNode.GetVersionHost().First = -1;
                    tNode.GetVersionHost().Second = 0;

                    if (tNode.GetVersionGuest().First == 0 && tNode.GetVersionGuest().Second == 0)
                    {
                        tNode.Isdeleted = true;
                    }
                }
                else
                {
                    tNode.GetVersionGuest().First = 0;
                    tNode.GetVersionGuest().Second = -1;

                    if (tNode.GetVersionHost().First == 0 && tNode.GetVersionHost().Second == 0)
                    {
                        tNode.Isdeleted = true;
                    }
                }
            }
            else
            {
                if (systemName == SystemType.Host)
                {
                    tNode.GetVersionHost().First = tNode.GetVersionGuest().First;
                    tNode.GetVersionHost().Second = tNode.GetVersionGuest().Second;
                }
                else
                {
                    tNode.GetVersionGuest().First = tNode.GetVersionHost().First;
                    tNode.GetVersionGuest().Second = tNode.GetVersionHost().Second;
                }
                tNode.Isdeleted = true;
            }
            return tNode;
        }

        public TreeNode CreationCreation(Difference diff, SystemType systemName)
        {
            TreeNode tNode = diff.GetPartnerFolder();

            if (diff.GetPairType().First == DirectionType.SystemToHD)
            {
                if (systemName == SystemType.Host)
                {
                    tNode.GetVersionHost().First++;
                }
                else
                {
                    tNode.GetVersionGuest().Second++;
                }
            }
            else
            {
                if (systemName == SystemType.Host)
                {
                    tNode.GetVersionHost().First = tNode.GetVersionGuest().First;
                    tNode.GetVersionHost().Second = tNode.GetVersionGuest().Second;
                }
                else
                {
                    tNode.GetVersionGuest().First = tNode.GetVersionHost().First;
                    tNode.GetVersionGuest().Second = tNode.GetVersionHost().Second;
                }
            }
            return tNode;
        }

        public TreeNode DeletionDeletion(Difference diff, SystemType systemName)
        {
            TreeNode tNode = diff.GetPartnerFolder();

            tNode.Isdeleted = true;
            return tNode;

        }

        public void PushToStack(Difference diff)
        {
            folderStack.Push(diff);
        }

        /// <summary>
        /// Updates the folders time and size since they will be modified for any file operation
        /// </summary>
        public void UpdateFoldersTimeandSize(List<TreeNode> arrNodes, SystemType systemName)
        {
            TreeNode tNode;
            String parsedDateTime;
            DirectoryInfo dirInfo;

            foreach (Difference diff in folderStack)
            {
                tNode = diff.GetPartnerFolder();
                try
                {
                    if (diff.GetPairType().Second == OperationType.Deletion)
                    {
                        parsedDateTime = Utility.ParseDateTime(DateTime.Now);
                        if (diff.GetPairType().First == DirectionType.SystemToHD)
                        {
                            if (systemName == SystemType.Host)
                            {
                                arrNodes[tNode.GetId()].SetSizeHost(0);
                                arrNodes[tNode.GetId()].SetSyncHost(parsedDateTime);
                            }
                            else
                            {
                                arrNodes[tNode.GetId()].SetSizeGuest(0);
                                arrNodes[tNode.GetId()].SetSyncGuest(parsedDateTime);
                            }
                        }
                        else
                        {
                            if (systemName == SystemType.Host)
                            {
                                DirectoryInfo D = new DirectoryInfo(tNode.GetFullPathHost());

                                if (D.GetDirectories().Length > 0 || D.GetFiles().Length > 0)
                                {
                                    arrNodes[tNode.GetId()].GetVersionHost().First = 1;
                                    arrNodes[tNode.GetId()].GetVersionHost().Second = 0;

                                    arrNodes[tNode.GetId()].GetVersionGuest().First = 0;
                                    arrNodes[tNode.GetId()].GetVersionGuest().Second = 0;
                                    arrNodes[tNode.GetId()].Isdeleted = false;
                                }
                                else
                                {
                                    // The directory's child are already deleted before executing this statement
                                    //Directory.Delete(tNode.GetFullPathHost());
                                    FileSystem.DeleteDirectory(tNode.GetFullPathHost(), UIOption.OnlyErrorDialogs, RecycleOption.SendToRecycleBin);
                                    arrNodes[tNode.GetId()].SetSizeHost(0);
                                    arrNodes[tNode.GetId()].SetSyncHost(parsedDateTime);
                                }
                            }
                            else
                            {
                                DirectoryInfo D = new DirectoryInfo(tNode.GetFullPathGuest());

                                if (D.GetDirectories().Length > 0 || D.GetFiles().Length > 0)
                                {
                                    arrNodes[tNode.GetId()].GetVersionHost().First = 0;
                                    arrNodes[tNode.GetId()].GetVersionHost().Second = 0;

                                    arrNodes[tNode.GetId()].GetVersionGuest().First = 0;
                                    arrNodes[tNode.GetId()].GetVersionGuest().Second = 1;
                                    arrNodes[tNode.GetId()].Isdeleted = false;
                                }
                                else
                                {
                                    // The directory's child are already deleted before before executing this statement
                                    //Directory.Delete(tNode.GetFullPathGuest());
                                    FileSystem.DeleteDirectory(tNode.GetFullPathGuest(), UIOption.OnlyErrorDialogs, RecycleOption.SendToRecycleBin);
                                    arrNodes[tNode.GetId()].SetSizeGuest(0);
                                    arrNodes[tNode.GetId()].SetSyncGuest(parsedDateTime);
                                }
                            }
                        }
                    }
                    else // other folders that are not delete type can be updated as normal
                    {
                        if (systemName == SystemType.Host)
                        {
                            dirInfo = new DirectoryInfo(tNode.GetFullPathHost());
                            long directorySize = Utility.CalculateDirectorySize(dirInfo);
                            parsedDateTime = Utility.ParseDateTime(dirInfo.LastWriteTime);
                            arrNodes[tNode.GetId()].SetSizeHost(directorySize);
                            arrNodes[tNode.GetId()].SetSyncHost(parsedDateTime);
                        }
                        else
                        {
                            dirInfo = new DirectoryInfo(tNode.GetFullPathGuest());
                            long directorySize = Utility.CalculateDirectorySize(dirInfo);
                            parsedDateTime = Utility.ParseDateTime(dirInfo.LastWriteTime);
                            arrNodes[tNode.GetId()].SetSizeGuest(directorySize);
                            arrNodes[tNode.GetId()].SetSyncGuest(parsedDateTime);
                        }
                    }
                }
                catch (UnauthorizedAccessException)
                {
                    if (systemName == SystemType.Host)
                        throw new UnauthorizedAccessException(tNode.GetFullPathHost(), ActionType.Sync);
                    else if (systemName == SystemType.Guest)
                        throw new UnauthorizedAccessException(tNode.GetFullPathGuest(), ActionType.Sync);
                }
                catch (DirectoryNotFoundException)
                {
                    if (systemName == SystemType.Host)
                        throw new DirectoryNotFoundException(tNode.GetFullPathHost(), ActionType.Sync);
                    else if (systemName == SystemType.Guest)
                        throw new DirectoryNotFoundException(tNode.GetFullPathGuest(), ActionType.Sync);
                }
                catch (PathTooLongException)
                {
                    if (systemName == SystemType.Host)
                        throw new PathTooLongException(tNode.GetFullPathHost(), ActionType.Sync);
                    else if (systemName == SystemType.Guest)
                        throw new PathTooLongException(tNode.GetFullPathGuest(), ActionType.Sync);
                }
            }
        }
    }
}
